
#include <dev.h>
#include "pic.h"

/* ------------------------------------------------------------------------- */

#define ist(ms)		ists[(ms) ? 1 : 0]
#define con(ms)		cons[(ms) ? 1 : 0]

/* ------------------------------------------------------------------------- */

typedef struct {
	uint8 icw1;
	uint8 icw2;
	uint8 icw3;
	uint8 icw4;
	uint8 ocw1;
	uint8 ocw2;
	uint8 ocw3;
	uint8 elcr;
} pic_reg_t;

/* ------------------------------------------------------------------------- */

static int ists[2];

static pic_reg_t cons[2];

/* ------------------------------------------------------------------------- */

void fastcall pic_init(void)
{
	int i;

	for (i = 0; i < 2; i++) {
		ists[i] = 0;
		cons[i].icw1 = 0x00;
		cons[i].icw2 = 0x00;
		cons[i].icw3 = 0x00;
		cons[i].icw4 = 0x01;
		cons[i].ocw1 = 0x00;
		cons[i].ocw2 = 0x20;
		cons[i].ocw3 = 0x22;
		cons[i].elcr = 0x00;
	}
}

uint8 fastcall pic_get_elcr(bool ms)
{
	write_log("[PIC] get %s ELCR = %02X", (ms ? "slave" : "master"), con(ms).elcr);

	return con(ms).elcr;
}

void fastcall pic_set_elcr(bool ms, uint8 data)
{
	write_log("[PIC] set %s ELCR = %02X", (ms ? "slave" : "master"), data);

	con(ms).elcr = data & (ms ? 0xfe : 0xf8);
}

uint8 fastcall pic_get_data(bool ms, int no)
{
	write_log("[PIC] get %s(%d) = %02X", (ms ? "slave" : "master"), no, (no ? con(ms).ocw1 : 0x00));

	return no ? con(ms).ocw1 : 0x00;
}

void fastcall pic_set_data(bool ms, int no, uint8 data)
{
	write_log("[PIC] set %s(%d) = %02X", (ms ? "slave" : "master"), no, data);

	if (!no) {
		switch (data & 0x18) {
		case 0x00:
			con(ms).ocw2 = data;
			return;
		case 0x08:
			con(ms).ocw3 = data;
			return;
		default:
			con(ms).icw1 = data & 0x1f;
			ist(ms)++;
			return;
		}
	}

	switch (ist(ms)) {
	case 0:
		con(ms).ocw1 = data;
		return;
	case 1:
		con(ms).icw2 = data & 0xf8;
		ist(ms)++;
		return;
	case 2:
		con(ms).icw3 = data;
		if (con(ms).icw1 & 0x01)
			ist(ms)++;
		else
			ist(ms) = 0;
		return;
	case 3:
		con(ms).icw4 = data & 0x1f;
		ist(ms) = 0;
		return;
	}
}

/* ------------------------------------------------------------------------- */
